/*
 * @(#)AbstractStoredQueryService.java
 * Date 2013-10-15
 * Version 1.0
 * Author Jim Horner
 * Copyright (c)2012
 */


package us.hornerscorners.lamppost.registry.service.es;

import java.util.Collection;

import javax.inject.Inject;

import oasis.names.tc.ebxml_regrep.xsd.query._3.AdhocQueryRequest;
import oasis.names.tc.ebxml_regrep.xsd.query._3.AdhocQueryResponse;

import oasis.names.tc.ebxml_regrep.xsd.rim._3.RegistryObjectListType;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import us.hornerscorners.lamppost.exception.ServiceActionError;
import us.hornerscorners.lamppost.exception.ServiceActionException;
import us.hornerscorners.lamppost.exception.ValidationException;

import us.hornerscorners.lamppost.model.audit.AuditContext;

import us.hornerscorners.lamppost.registry.constant.ResponseStatus;

import us.hornerscorners.lamppost.registry.inject.RegistryTarget;

import us.hornerscorners.lamppost.registry.model.QueryRequest;
import us.hornerscorners.lamppost.registry.model.QueryResponse;

import us.hornerscorners.lamppost.registry.query.es.IQueryRunner;
import us.hornerscorners.lamppost.registry.query.es.IQueryRunnerFactory;

import us.hornerscorners.lamppost.registry.service.AtnaRegistryService;
import us.hornerscorners.lamppost.registry.service.IStoredQueryService;

import us.hornerscorners.lamppost.registry.transformer.xds.RegistryObjectListTransformer;
import us.hornerscorners.lamppost.registry.transformer.xds
    .RegistryResponseTypeTransformer;

import us.hornerscorners.lamppost.transformer.ITransformer;


/**
 * Class description
 *
 *
 * @version        v1.0, 2013-10-15
 * @author         Jim Horner
 */
public abstract class AbstractStoredQueryService implements IStoredQueryService {

    /** Field description */
    @Inject
    private AtnaRegistryService atnaService;

    /** Field description */
    private final Logger logger = LoggerFactory.getLogger(getClass());

    /** Field description */
    @Inject
    private RegistryObjectListTransformer registryObjectTransformer;

    /** Field description */
    @Inject
    @RegistryTarget
    private RegistryResponseTypeTransformer registryResponseTransformer;

    /**
     * ITI-18 Registry Stored Query
     *
     *
     * @param body
     *
     * @return
     *
     */
    @Override
    public AdhocQueryResponse executeStoredQuery(AuditContext auditContext,
            AdhocQueryRequest body) {

        AdhocQueryResponse result = new AdhocQueryResponse();

        QueryRequest queryRequest = null;
        QueryResponse queryResponse = null;

        try {

            queryRequest = getQueryRequestTransformer().transform(body);

            IQueryRunner queryRunner =
                getQueryRunnerFactory().createQueryRunner(queryRequest);

            queryResponse = queryRunner.run(queryRequest);

            Collection<ServiceActionError> errors =
                queryRunner.validateResponse(queryResponse);

            if (errors.isEmpty()) {

                result.setRegistryObjectList(
                    this.registryObjectTransformer.transform(queryResponse));

                result.setStatus(ResponseStatus.Success.getCode());

            } else {

                result.setRegistryObjectList(new RegistryObjectListType());
                result.setStatus(ResponseStatus.Failure.getCode());

                ValidationException ex = new ValidationException(getClass(), errors);

                result.setRegistryErrorList(
                    this.registryResponseTransformer.createRegistryErrorList(ex));
            }

        } catch (ServiceActionException e) {

            logger.error(e.getMessage(), e);
            result.setRegistryObjectList(new RegistryObjectListType());
            result.setStatus(ResponseStatus.Failure.getCode());
            result.setRegistryErrorList(
                this.registryResponseTransformer.createRegistryErrorList(e));

        } finally {

            this.atnaService.sendQueryReceivedAuditMessage(auditContext, body, result);
        }

        return result;
    }

    /**
     * Method description
     *
     *
     * @return
     */
    protected abstract ITransformer<AdhocQueryRequest,
                                    QueryRequest> getQueryRequestTransformer();

    /**
     * Method description
     *
     *
     * @return
     */
    protected abstract IQueryRunnerFactory getQueryRunnerFactory();

    /**
     * Method description
     *
     *
     * @return
     */
    protected RegistryObjectListTransformer getRegistryObjectTransformer() {
        return registryObjectTransformer;
    }

    /**
     * Method description
     *
     *
     * @return
     */
    protected RegistryResponseTypeTransformer getRegistryResponseTransformer() {
        return registryResponseTransformer;
    }
}
